/*
 * XMLElement.cpp
 *
 *  Created on: 2010-3-25
 *      Author: wenjian
 */

#include <string.h>
#include "XMLElement.h"
#include "XMLDocument.h"

using namespace std;

namespace Try {

  XMLElement::XMLElement(XMLDocument* doc, const char* n)
    :xmldoc(doc), parent(NULL), name(NULL), text(NULL){
    setName(n);
  }

  XMLElement::~XMLElement() {
    if(name!=NULL)delete[] name;
    if(name!=text)delete[] text;
  }


  /**
   * 检查是否是根元素
   */
   bool XMLElement::isRootElement() const{
     return xmldoc->getRootElement() == this;
   }

  /**
   * 返回元素名称
   */
   const char* XMLElement::getName() const{
     return name;
   }

  /**
   * 设置元素名称
   */
   void XMLElement::setName(const char* name){
     if(name!=NULL){
       unsigned int len = strlen(name);
       if(this->name==NULL){
         this->name = new char[len+1];
       }else if(strlen(this->name)<len){
         char* tmp = this->name;
         this->name = new char[len+1];
         delete[] tmp;
       }
       strcpy(this->name, name);
     }
   }

  /**
   * 返回元素文本值
   */
   const char* XMLElement::getText() const{
     return text;
   }

  /**
   * 设置元素文本值
   */
   XMLElement* XMLElement::setText(const char* text){
     if(text!=NULL){
       unsigned int len = strlen(text);
       if(this->text==NULL){
         this->text = new char[len+1];
       }else if(strlen(this->text)<len){
         char* tmp = this->text;
         this->text = new char[len+1];
         delete[] tmp;
       }
       strcpy(this->text, text);
     }
     return this;
   }

  /**
   * 返回所有子元素列表
   */
   const std::vector<XMLElement*>* XMLElement::getChildren() const{
     return &children;
   }

  /**
   * 根据元素名称在参数vector中返回子元素列表
   */
   std::vector<XMLElement*>* XMLElement::getChildren(const char* name, std::vector<XMLElement*>* v) const{
     std::vector<XMLElement*>::const_iterator it = children.begin();
     for(; it!=children.end(); it++){
       XMLElement* e = *it;
       if(strcmp(e->name,name)==0){
         v->push_back(e);
       }
     }
     return v;
   }

  /**
   * 返回第一个名称为name的子元素
   */
   XMLElement* XMLElement::getChild(const char* name) const{
     std::vector<XMLElement*>::const_iterator it = children.begin();
     for(; it!=children.end(); it++){
       XMLElement* e = *it;
       if(strcmp(e->name,name)==0){
         return e;
       }
     }
     return NULL;
   }

  /**
   * 向元素追加一个子元素, 返回this
   */
   XMLElement* XMLElement::addChild(XMLElement* child){
     children.push_back(child);
     child->parent = this;
     return this;
   }

  /**
   * 在子元素列表的指定位置插入一个子元素, 返回this
   */
   XMLElement* XMLElement::addChild(int index, XMLElement* child){
     children.insert(children.begin()+index, child);
     child->parent = this;
     return this;
   }

  /**
   * 移除名称为name的第一个子元素, 如果移除失败，返回false, 比如此元素不存在
   */
   bool XMLElement::removeChild(const char* name){
     std::vector<XMLElement*>::iterator it = children.begin();
     for(; it!=children.end(); it++){
       XMLElement* e = *it;
       if(strcmp(e->name,name)==0){
         children.erase(it);
         e->parent = NULL;
         return true;
       }
     }
     return false;
   }

  /**
   * 移除子元素, 如果移除失败，返回false, 比如此元素不存在
   */
   bool XMLElement::removeChild(const XMLElement* e){
     std::vector<XMLElement*>::iterator it = find(children.begin(), children.end(), e);
     if(it != children.end()){
       children.erase(it);
       (*it)->parent = NULL;
       return true;
     }
     return false;
   }

  /**
   * 移除名称为name的所有（只操作下一层）子元素, 如果没有任何一个元素被移除，返回false
   */
   bool XMLElement::removeChildren(const char* name){
     bool flag = false;
     std::vector<XMLElement*>::iterator it = children.begin();
     for(; it!=children.end(); it++){
       XMLElement* e = *it;
       if(strcmp(e->name,name)==0){
         children.erase(it);
         e->parent = NULL;
         flag = true;
       }
     }
     return flag;
   }

  /**
   * 移除所有（只操作下一层）子元素, 如果没有任何一个元素被移除，返回false
   */
   bool XMLElement::removeChildren(){
     if(children.size()==0){
       return false;
     }
     std::vector<XMLElement*>::iterator it = children.begin();
     for(; it!=children.end(); it++){
        (*it)->parent = NULL;
     }
     children.clear();
     return true;
   }

  /**
   * 返回元素属性
   */
   XMLAttribute* XMLElement::getAttribute(const char* name)const{
     std::vector<XMLAttribute*>::const_iterator it = attrs.begin();
     for(; it!=attrs.end(); it++){
       XMLAttribute* attr = *it;
       if(strcmp(attr->getName(),name)==0){
         return attr;
       }
     }
     return NULL;
   }

  /**
   * 返回所有属性
   */
   const std::vector<XMLAttribute*>* XMLElement::getAttributes()const{
     return &attrs;
   }

  /**
   * 根据属性名返回属性值
   */
   const char* XMLElement::getAttributeValue(const char* name)const{
     XMLAttribute* attr = getAttribute(name);
     return attr==NULL?NULL:attr->getValue();
   }

  /**
   * 设置属性
   */
   XMLElement* XMLElement::setAttribute(XMLAttribute* a){
     attrs.push_back(a);
     return this;
   }

  /**
   * 设置属性
   */
   XMLElement* XMLElement::setAttribute(const char* name, const char* value){
     attrs.push_back(xmldoc->newAttribute(name, value));
     return this;
   }

   /**
    * 返回父节点，如果不存在，返回NULL
    */
   XMLElement* XMLElement::getParent(){
     return parent;
   }

   /**
    * 从父节点分离
    */
   XMLElement* XMLElement::detach(){
     if(parent!=NULL){
       parent->removeChild(this);
     }
     return this;
   }
}
